﻿using System;
using System.Linq;
using BaMusaSoft.RPS.ViewModel.Infrastructure;
using BaMusaSoft.RPS.WinIRSService;
using BaMusaSoft.RPS.ViewModel.Properties;
using BaMusaSoft.RPS.DataModel;
using BaMusaSoft.RPS.RPSServices;

using System.Windows.Input;
using System.Threading.Tasks;
using System.Windows.Threading;
using SysWindows = System.Windows;
using System.Data.Objects;

namespace BaMusaSoft.RPS.ViewModel
{
    public class SyncViewModel : Workspace
    {
        //#region "Fields"

        ////RPSSyncWithIRSService rpsSyncWithIRS;
        //ObjectSet<Customer> rpsCustomers;            //Note: Using of ObjectSet<> has an advantage over .NET collections that it tracks changes made to the collection, so you don't need to do that manually
        //ObjectSet<Contract> rpsContracts;            //Note: Using of ObjectSet<> has an advantage over .NET collections that it tracks changes made to the collection, so you don't need to do that manually
        //ObjectSet<Payment> rpsPayments;              //Note: Using of ObjectSet<> has an advantage over .NET collections that it tracks changes made to the collection, so you don't need to do that manually
        //ObjectSet<ScheduleDetail> rpsDetails;        //Note: Using of ObjectSet<> has an advantage over .NET collections that it tracks changes made to the collection, so you don't need to do that manually
        //ObjectSet<Property> rpsProperties;           //Note: Using of ObjectSet<> has an advantage over .NET collections that it tracks changes made to the collection, so you don't need to do that manually
        //ObjectSet<Schedule> rpsScheduleds;
        //int currentYear;
        //DelegateCommand syncCommand;
        //DelegateCommand saveCommand;
        //double syncProgress;
        //SysWindows.Visibility currentSyncVisibility;
        //string currentSync;
        //volatile bool succeeded;
        //Dispatcher currentDispacher;
        //bool canSyncProperties;
        //Settings settings;
        //Logger logger;
        //private readonly string _irsDbPath;
        //#endregion
        //public SyncViewModel()
        //{
        //    //settings = Settings.Default;
        //    //logger = new Logger(settings.LogFilePath);
        //    ////rpsSyncWithIRS = new RPSSyncWithIRSService();
        //    //_irsDbPath = settings.IRSDatabasePath;

        //    //currentYear = int.Parse(Settings.Default.CurrentYear.Substring(2,2));
        //    //CurrentSyncVisibilty = SysWindows.Visibility.Hidden;
        //    //DisplayName = Resources.SyncViewModel_DisplayName;
        //    //currentDispacher = Dispatcher.CurrentDispatcher;
        //    //CanSyncProperties = true;


        //}
        //#region "Properties"

        //public double SyncProgress
        //{
        //    get { return syncProgress; }
        //    set
        //    {
        //        if (value != syncProgress)
        //        {
        //            syncProgress = value;
        //            RaisePropertyChanged("SyncProgress");
        //        }
        //    }
        //}
        //public SysWindows.Visibility CurrentSyncVisibilty
        //{
        //    get { return currentSyncVisibility; }
        //    set
        //    {
        //        if (value != currentSyncVisibility)
        //        {
        //            currentSyncVisibility = value;
        //            RaisePropertyChanged("CurrentSyncVisibilty");
        //        }
        //    }
        //}
        //public string CurrentSync
        //{

        //    get { return currentSync; }
        //    set
        //    {
        //        if (value != currentSync)
        //        {
        //            currentSync = value;
        //            RaisePropertyChanged("CurrentSync");
        //        }
        //    }
        //}
        //public bool CanSyncProperties
        //{
        //    get { return canSyncProperties; }
        //    set
        //    {
        //        if (value != canSyncProperties)
        //        {
        //            canSyncProperties = value;
        //            RaisePropertyChanged("CanSyncProperties");
        //        }
        //    }
        //}
        //#endregion

        //#region "Commands"
        //public ICommand SyncCommand
        //{
        //    get
        //    {
        //        if (syncCommand == null)
        //        {
        //            syncCommand = new DelegateCommand(param => Sync(), param => CanSync());
        //        }
        //        return syncCommand;
        //    }
        //}
        //void Sync()
        //{
        //    Task task = Task.Factory.StartNew(() => AsyncSyncWithIRS());
        //}
        //bool CanSync()
        //{
        //    return (succeeded == false);
        //}
        //public ICommand SaveCommand
        //{
        //    get
        //    {
        //        if (saveCommand == null)
        //        {
        //            saveCommand = new DelegateCommand(param => Save(), param => CanSave());
        //        }
        //        return saveCommand;
        //    }
        //}
        //private void Save()
        //{
        //    try
        //    {
        //        //rpsSyncWithIRS.Save();
        //        succeeded = false;

        //    }
        //    catch (Exception ex)
        //    {
        //        if (ex.InnerException != null)
        //        {
        //            logger.Error(ex.InnerException, "SyncViewModel", "Sync");
        //        }
        //        else
        //        {
        //            logger.Error(ex, "SyncViewModel", "Sync");
        //        }
        //        string msg = ex.Message;
        //        ShowError(msg);

        //    }
        //}
        //private bool CanSave()
        //{
        //    return (succeeded == true);
        //}
        //#endregion
        //        #region "Methods"
        //        private void AsyncSyncWithIRS()
        //        {
        //            try
        //            {
        //                //CurrentSyncVisibilty = SysWindows.Visibility.Visible;
        //                //SyncCustomers();         //Always sync Customers befor Contracts due to database releationship. (1-*)
        //                //SyncContracts();
        //                //SyncPayments();         //Always sync payements befor updateDetailsAmountPaid as the latter depend on the SyncPayments.
        //                //UpdateDetailsAmountPaid();
        //                //if (CanSyncProperties) SyncProperties();
        //                //succeeded = true;
        //                //Console.WriteLine(succeeded);


        //            }
        //            catch (Exception ex)
        //            {
        //                if (ex is ObjectDisposedException) //User had closed the the window just log the info, then swallow.
        //                {
        //                    logger.Error(ex, "SyncViewModel", "Sync");
        //                    return;
        //                }
        //                if (ex.InnerException != null)
        //                {
        //                    logger.Error(ex.InnerException, "SyncViewModel", "Sync");
        //                }
        //                else
        //                {
        //                    logger.Error(ex, "SyncViewModel", "Sync");
        //                }
        //                string msg = "the folowing Error occured while sync data. \n No data has been saved in the database: \n" + ex.Message;
        //                ShowError(msg);
        //            }
        //            finally
        //            {
        //                CurrentSyncVisibilty = SysWindows.Visibility.Hidden;
        //                SyncProgress = 0.0;
        //            }
        //        }
        //        private void SyncCustomers()
        //        {
        //            //rpsCustomers = rpsSyncWithIRS.GetAllCustomers();
        //            //var irsCustomers = new CustomerTableAdapter(_irsDbPath).GetData();
        //            //double count = irsCustomers.Count;
        //            //double current = 0.0;
        //            //UpdateCurrentSyncLable(Resources.SyncCustomersLabel);
        //            //SyncProgress = 0.0;
        //            //foreach (Customer irsCustomer in irsCustomers)
        //            //{
        //            //    bool exist = rpsCustomers.Any(cus => cus.CustomerId == irsCustomer.CustomerId);
        //            //    if (!exist) //If new Add it
        //            //    {
        //            //        rpsCustomers.AddObject(irsCustomer);
        //            //    }
        //            //    else //Otherwise udpate it.
        //            //    {
        //            //        var existingCustomer = rpsCustomers.SingleOrDefault(x => x.CustomerId == irsCustomer.CustomerId);
        //            //        existingCustomer.Name = irsCustomer.Name;
        //            //    }
        //            //    current++;
        //            //    UpdateProgress(count, current);
        //            //}
        //        }
        //        //private void SyncContracts()
        //        //{
        //        //    //rpsContracts = rpsSyncWithIRS.GetAllContracts();
        //        //    //var irsContracts = new ContractTableAdapter(_irsDbPath).GetData();
        //        //    //double count = irsContracts.Count;
        //        //    //double current = 0.0;
        //        //    //UpdateCurrentSyncLable(Resources.SyncContractsLabel);
        //        //    //SyncProgress = 0.0;
        //        //    //foreach (Contract irsContract in irsContracts)
        //        //    //{
        //        //    //    bool exist = rpsContracts.Any(contr => contr.ContractNo == irsContract.ContractNo);
        //        //    //    if (!exist) //If new Add it
        //        //    //    {
        //        //    //        rpsContracts.AddObject(irsContract);
        //        //    //    }
        //        //    //    else //Otherwise udpate it.
        //        //    //    {
        //        //    //        var existingContract = rpsContracts.SingleOrDefault(x => x.ContractNo == irsContract.ContractNo);
        //        //    //        existingContract.StartDate = irsContract.StartDate;
        //        //    //        existingContract.EndDate = irsContract.EndDate;
        //        //    //        existingContract.CustomerId = irsContract.CustomerId;
        //        //    //        existingContract.PropertyNo = irsContract.PropertyNo;
        //        //    //        existingContract.Closed = irsContract.Closed;
        //        //    //        existingContract.AgreedRent = irsContract.AgreedRent;
        //        //    //        existingContract.AgreedDeposit = irsContract.AgreedDeposit;
        //        //    //        existingContract.AgreedMaintenance = irsContract.AgreedMaintenance;
        //        //    //        existingContract.RentBalance = irsContract.RentBalance;
        //        //    //        existingContract.MaintenanceBalance = irsContract.MaintenanceBalance;
        //        //    //        existingContract.DepositBalance = irsContract.DepositBalance;
        //        //    //        existingContract.Total = irsContract.RentBalance + irsContract.MaintenanceBalance + irsContract.DepositBalance;
        //        //    //    }
        //        //    //    current++;
        //        //    //    UpdateProgress(count, current);
        //        //    //}
        //        //}
        //        //private void SyncPayments()
        //        //{
        //        //    //rpsPayments = rpsSyncWithIRS.GetAllPayments();
        //        //    //var irsPayments = new PaymentsTableAdapter(_irsDbPath).GetData();
        //        //    //double count = irsPayments.Count;
        //        //    //double current = 0.0;
        //        //    //UpdateCurrentSyncLable(Resources.SyncPaymentsLable);
        //        //    //SyncProgress = 0.0;
        //        //    //foreach (Payment irsPayment in irsPayments)
        //        //    //{
        //        //    //    bool exist = rpsPayments.Any(pay => pay.ContractNo == irsPayment.ContractNo);
        //        //    //    if (!exist) //If new Add it
        //        //    //    {
        //        //    //        irsPayment.UnscheduledPayment = irsPayment.TotalPayment;
        //        //    //        rpsPayments.AddObject(irsPayment);
        //        //    //    }
        //        //    //    else //Otherwise udpate it.
        //        //    //    {
        //        //    //        var existingPayments = rpsPayments.SingleOrDefault(pay => pay.ContractNo == irsPayment.ContractNo);
        //        //    //        //Check If had scheduled
        //        //    //        bool scheduled = HadScheduled(irsPayment.ContractNo);
        //        //    //        if (!scheduled) //If not scheduled yet then:
        //        //    //        {
        //        //    //            existingPayments.UnscheduledPayment = irsPayment.TotalPayment;
        //        //    //        }
        //        //    //        else //but if it had scheduled, then:
        //        //    //        {
        //        //    //            int totalPaymentInIRS = irsPayment.TotalPayment;                    // Get The total payments From IRS
        //        //    //            int unscheduledPaymentInRPS = existingPayments.UnscheduledPayment; // Get payments that is already registred in the RPS, which represents the amount befor making the schedule
        //        //    //            int amountPaidForSchedule = totalPaymentInIRS - unscheduledPaymentInRPS;  //This is the net amount that is paid for our schedule
        //        //    //            existingPayments.ScheduledPayment = amountPaidForSchedule; //Update scheduled payment.
        //        //    //        }
        //        //    //    }
        //        //    //    current++;
        //        //    //    UpdateProgress(count, current);
        //        //    //}

        //        //}
        //        //private void UpdateDetailsAmountPaid()
        //        ////{
        //            //rpsScheduleds = rpsSyncWithIRS.GetAllSchedules();
        //            //rpsDetails = rpsSyncWithIRS.GetAllDetails();
        //            //double count = rpsScheduleds.Count();
        //            //double current = 0.0;
        //            //UpdateCurrentSyncLable(Resources.SyncAmountPaidLabel);
        //            //SyncProgress = 0.0;
        //            //foreach (Schedule schedule in rpsScheduleds)
        //            //{
        //            //    //Get Details of for this Schedules.
        //            //    var scheduleDetails = rpsDetails.Where(x => x.ScheduleId == schedule.ScheduleId);
        //            //    //Get Payements paid for the contract this schedule registred with.
        //            //    var SchedulePayemtents = rpsPayments.Where(x => x.ContractNo == schedule.ContractNo).FirstOrDefault();
        //            //    if (SchedulePayemtents != null) // Ensure there is payments paid for the contract befor proceed.
        //            //    {
        //            //        /* Starting of update AmountPaid algorithem
        //            //         * This algorithem takes the total amount paid for schedule, that's 'ScheduledPayment' 
        //            //         * (we have another amount called UnscheduledPayment to maintain the amount paid for contract befor creating the schedule)
        //            //         * then iterate over the schedule details of the given 'Schedule'
        //            //         * each time we iterate it gets the AmountDue field and see if the total we have
        //            //         * is enough to pay the AmountDue; if it is then pay it and extract the AmountDue from total
        //            //         * if doesn't just pay the remanining amount in total to AmountDue 
        //            //         * Note: That this algorithem doesn't cover the case when property application 
        //            //         * change the total amount paid for contract by minus as this unlikely to be happend
        //            //         * but if it does any AmounPaid that paid previously will not be adjusted, so take a note of this limitation.
        //            //         */
        //            //        int total = SchedulePayemtents.ScheduledPayment;
        //            //        foreach (ScheduleDetail detail in scheduleDetails)
        //            //        {
        //            //            int detailAmountDue = detail.AmountDue;
        //            //            if (total >= detailAmountDue)
        //            //            {
        //            //                detail.AmountPaid = detailAmountDue;
        //            //                detail.Balance = 0;
        //            //                total = total - detailAmountDue;
        //            //            }
        //            //            else if (total > 0 && total < detailAmountDue)
        //            //            {
        //            //                detail.AmountPaid = total;
        //            //                int balance = detailAmountDue - total;
        //            //                detail.Balance = balance;
        //            //                total = total - total;
        //            //            }
        //            //        }
        //            //        current++;
        //            //        UpdateProgress(count, current);
        //            //    }

        //            }

        //            //rpsDetails = rpsSyncWithIRS.GetAllDetails();
        //            //double count = rpsPayments.Count();
        //            //double current = 0.0;
        //            //UpdateCurrentSyncLable(Resources.SyncAmountPaidLabel);
        //            //SyncProgress = 0.0;
        //            //foreach (Payment payment in rpsPayments)
        //            //{
        //            //    var scheduleDetailsForContract = rpsDetails.Where(detail => detail.ContractNo == payment.ContractNo).ToList();
        //            //    if (scheduleDetailsForContract.Count > 0)
        //            //    {
        //            //        /* Starting of update AmountPaid algorithem
        //            //         * This algorithem takes the total amount paid for schedule, that's 'ScheduledPayment' 
        //            //         * (we have another amount called UnscheduledPayment to maintain the amount paid for contract befor creating the schedule)
        //            //         * then iterate over the schedule details of the given 'ContractNo'
        //            //         * each time we iterate it gets the AmountDue field and see if the total we have
        //            //         * is enough to pay the AmountDue; if it is then pay it and extract the AmountDue from total
        //            //         * if doesn't just pay the remanining amount in total to AmountDue 
        //            //         * Note: That this algorithem doesn't cover the case when property application 
        //            //         * change the total amount paid for contract by minus as this unlikely to be happend
        //            //         * but if it does any AmounPaid that paid previously will not be adjusted, so take a note of this limitation.
        //            //         */
        //            //        int total = payment.ScheduledPayment;
        //            //        foreach (ScheduleDetail detail in scheduleDetailsForContract)
        //            //        {
        //            //            int detailAmountDue = detail.AmountDue;
        //            //            if (total >= detailAmountDue)
        //            //            {
        //            //                detail.AmountPaid = detailAmountDue;
        //            //                detail.Balance = 0;
        //            //                total = total - detailAmountDue;
        //            //            }
        //            //            else if (total > 0 && total < detailAmountDue)
        //            //            {
        //            //                detail.AmountPaid = total;
        //            //                int balance = detailAmountDue - total;
        //            //                detail.Balance = balance;
        //            //                total = total - total;
        //            //            }
        //            //        }
        //            //    }
        //            //    current++;
        //            //    UpdateProgress(count, current);
        //            //}
        //        //}

        //        //private void SyncProperties()
        //        //{
        //        //    rpsProperties = rpsSyncWithIRS.GetAllProperties();
        //        //    var irsProperties = new PropertiesTableAdpater(_irsDbPath).GetData();
        //        //    double count = irsProperties.Count;
        //        //    double current = 0.0;
        //        //    UpdateCurrentSyncLable(Resources.SyncPropertiesLable);
        //        //    SyncProgress = 0.0;
        //        //    foreach (Property irsProperty in irsProperties)
        //        //    {
        //        //        bool exist = rpsProperties.Any(p => p.PropertyNo == irsProperty.PropertyNo);
        //        //        if (!exist) //If new Add it
        //        //        {
        //        //            rpsProperties.AddObject(irsProperty);
        //        //        }
        //        //        else //Otherwise udpate it.
        //        //        {
        //        //            var existingProperty = rpsProperties.SingleOrDefault(p => p.PropertyNo == irsProperty.PropertyNo);
        //        //            existingProperty.Type = irsProperty.Type;
        //        //            existingProperty.Location = irsProperty.Location;
        //        //            existingProperty.Description = irsProperty.Description;
        //        //        }
        //        //        current++;
        //        //        UpdateProgress(count, current);
        //        //    }
        //        //}

        //        //#endregion
        //        //#region "Helper Methods"
        //        //private void UpdateProgress(double count, double current)
        //        //{
        //        //    var p = (current / count) * 100;
        //        //    Action action = () => SyncProgress = p;
        //        //    currentDispacher.Invoke(action, null);
        //        //}

        //        //private void ShowError(string msg)
        //        //{
        //        //    //Action<String> action = (m) => MessageBox.Show(m, "RPS", SysWindows.MessageBoxButton.OK, SysWindows.MessageBoxImage.Error);
        //        //    //currentDispacher.Invoke(action, new string[] { msg });
        //        //}
        //        //private void UpdateCurrentSyncLable(string msg)
        //        //{
        //        //    Action<string> action = (currentOps) => CurrentSync = currentOps;
        //        //    currentDispacher.Invoke(action, new string[] { msg });
        //        //}
        //        //private bool HadScheduled(int contractNo)
        //        //{
        //        //    //return rpsSyncWithIRS.HadScheduled(contractNo);
        //        //    return true;
        //        //}
        //        //#endregion

        //        //#region Overrides of Workspace

        //        //public override string DisplayName
        //        //{
        //        //    get { throw new NotImplementedException(); }
        //        //    protected set { throw new NotImplementedException(); }
        //        //}

        //        //public override bool HasChanges
        //        //{
        //        //    get { throw new NotImplementedException(); }
        //        //}

        //        //#endregion
        //    }
        //}

        #region Overrides of Workspace

        public override string DisplayName
        {
            get { throw new NotImplementedException(); }
            protected set { throw new NotImplementedException(); }
        }

        public override bool HasChanges
        {
            get { throw new NotImplementedException(); }
        }

        #endregion

    }
}
